# coding=utf8
from pyjvm.classfile.attrs import *
from pyjvm.utils import *
from typing import Optional, List
from pyjvm.classfile.reader import ClassBytesReader
from pyjvm.classfile.constpool import ConstantPool


class FieldAccessFlag:
    ACC_PUBLIC = 0x0001  # 声明为public 可以用外包访问
    ACC_PRIVATE = 0x0002  # 声明为private 该类内才能访问
    ACC_PROTECTED = 0x0004  # 声明为protected 子类才能访问
    ACC_STATIC = 0x0008  # 声明为static 静态成员
    ACC_FINAL = 0x0010  # 声明为final 对象构造好之后，就不能直接设置该字段
    ACC_VOLATILE = 0x0040  # 声明为volatile，被标识的字段无法缓存
    ACC_TRANSIENT = 0x0080  # 声明为transient，被标识的字段不会为持久化对象管理器所写入或读取
    ACC_SYNTHETIC = 0x1000  # synthetic，该字段由编译器产生，不是由java代码生成的
    ACC_ENUM = 0x4000  # enum


class MethodAccessFlag:
    ACC_PUBLIC = 0x0001  # 声明为public 可以用外包访问
    ACC_PRIVATE = 0x0002  # 声明为private 该类内才能访问
    ACC_PROTECTED = 0x0004  # 声明为protected 子类才能访问
    ACC_STATIC = 0x0008  # 声明为static 静态成员
    ACC_FINAL = 0x0010  # 声明为final 对象构造好之后，就不能直接设置该字段
    ACC_SYNCHRONIZED = 0x0020  # 声明为synchronized 对该方法的调用，将包装在同步锁（monitor）里
    ACC_BRIDGE = 0x0040  # 声明为brigdge方法，由编译器产生
    ACC_VARARGS = 0x0080  # 表示方法有变长参数
    ACC_NATIVE = 0x0100  # 声明为native方法（非java语言实现)
    ACC_ABSTRACT = 0x0400  # 声明为abstract方法
    ACC_STRICT = 0x0800  # 声明为strictfp 使用Fp-strict浮点模式
    ACC_SYNTHETIC = 0x1000  # synthetic，该字段由编译器产生，不是由java代码生成的


class ClassMemberInfo:

    def __init__(self):
        self.access_flags: Optional[int] = None
        self.name: Optional[str] = None
        self.descriptor: Optional[str] = None
        self.attributes: Optional[List[AttributeInfo]] = None

    def new(self, reader: ClassBytesReader, cp: ConstantPool):
        self.access_flags = reader.uint16()
        self.name = cp.read_utf8(reader)
        self.descriptor = cp.read_utf8(reader)
        self.attributes = AttributeInfo.read_attributes(reader, cp)

    def __str__(self):
        return '''%s[name:%s, 
        descriptor:%s,
        attributes:[%s]]''' % (self.__class__.__name__,
                               self.name, self.descriptor, iter_readable(self.attributes))


class FieldInfo(ClassMemberInfo):
    pass


class MethodInfo(ClassMemberInfo):
    pass


__all__ = ['ClassMemberInfo', 'MethodInfo', 'FieldInfo']
